//
//  ImageCacheHelper.m
//  WoWeibo
//
//  Created by Jaedong n.Die_ on 12-5-31.
//  Copyright (c) 2012年 __MyCompanyName__. All rights reserved.
//

#import "ImageCacheHelper.h"

#import "ImageDownloadHelper.h"
#import "MD5Extension.h"
#import "ImageStoreHelper.h"

@implementation ImageCacheHelper

static ImageCacheHelper *imageCacheHelper = nil;

+ (ImageCacheHelper *)sharedImageCacheHelper {

    if(imageCacheHelper == nil) {
    
        imageCacheHelper = [[super allocWithZone:NULL] init];
    }
    
    return imageCacheHelper;
}

- (id)init {
    
    self = [super init];
    if(self) {
        
        _maxCacheCount = 10;
        _imagesCache = [[NSMutableDictionary alloc] init];
        _delegateDict = [[NSMutableDictionary alloc] init];
        _imageDownloadHelper = [[ImageDownloadHelper alloc] init];
    }
    
    return self;
}

+ (id)allocWithZone:(NSZone *)zone
{
    return [[self sharedImageCacheHelper] retain];
}

- (id)copyWithZone:(NSZone *)zone
{
    return self;
}

- (id)retain
{
    return self;
}

- (NSUInteger)retainCount
{
    return NSUIntegerMax;
}

- (oneway void)release
{
    //do nothing
}

- (id)autorelease
{
    return self;
}

- (void)dealloc {

    [_imagesCache release];
    [_delegateDict release];
    
    _imagesCache = nil;
    _delegateDict = nil;
    
    [super dealloc];
}

#pragma mark -
#pragma mark Instance Methods.

- (NSData *)getImageByURL:(NSURL *)imageURL withDelegate:(id<ImageDownloadOperationDelegate>)delegate {

    // Search the |imageURL| in |_imageCache|.
    NSData *imageData = [_imagesCache objectForKey:imageURL.absoluteString];
    if(imageData == nil) {
    
        // Search the |_imageURL| in disk.
        imageData = [[ImageStoreHelper sharedImageStoreHelper] getDataByName:[imageURL.absoluteString MD5]];
        if(imageData == nil) {
            
            // Search the |_imageURL| in |_delegateDict| to find is there a same request has being downloading,
            // if find, then add the |delegate| in to |_delegateDict|, else, request to download image.
            NSMutableArray *delegateArray = [_delegateDict objectForKey:imageURL.absoluteString];
            if(delegateArray == nil) {
                
                delegateArray = [NSMutableArray arrayWithCapacity:10];
                [delegateArray addObject:delegate];
                [_delegateDict setObject:delegateArray forKey:imageURL.absoluteString];
                [_imageDownloadHelper downloadImageWithURL:imageURL fromTarget:self];
            }else {
                
                if(![delegateArray containsObject:delegate])
                    [delegateArray addObject:delegate];
            }
        }
    }
    
    return imageData;
}

- (void)saveCache {
    
    // Write the image into disk, and remove all objects in |_imagesCache|.
    for (NSString *key in _imagesCache.allKeys) {
        
        [[ImageStoreHelper sharedImageStoreHelper] storeData:[_imagesCache objectForKey:key] withName:[key MD5]];
//        [[ImageStoreHelper sharedImageStoreHelper] writeFile:[key MD5]
//                                                withFileData:UIImageJPEGRepresentation((UIImage *)[_imagesCache objectForKey:key], 1.0f)];
    }
    
    [_imagesCache removeAllObjects];
}

#pragma mark -
#pragma mark ImageDownloadOperationDelegate Support.

- (void)imageDidDownloadSuccessed:(NSData *)imageData withURL:(NSURL *)imageURL {
    
    // Notify the delegates.
    NSMutableArray *delegateArray = [_delegateDict objectForKey:imageURL.absoluteString];
    for (id delegate in delegateArray) {
        
        if(delegate != nil && [delegate respondsToSelector:@selector(imageDidDownloadSuccessed:withURL:)]) {
        
            [delegate imageDidDownloadSuccessed:imageData withURL:imageURL];
        }
    }
    
    // Remove the key & value from delegateArray;
    [_delegateDict removeObjectForKey:imageURL.absoluteString];
    
    // Check the image cache's max count, if it's equal to |_maxCacheCount|,
    // then save the images into disk and clear the |_imageCache|.
    if(_imagesCache.count == _maxCacheCount) {
        
        [self saveCache];
    }
    
    // Insert the image into |_imageCache|.
    [_imagesCache setObject:imageData forKey:imageURL.absoluteString];
}

- (void)imageDidDownloadFailed:(NSURL *)imageURL {

    // Find the delegates and notify them.
    NSMutableArray *delegateArray = [_delegateDict objectForKey:imageURL.absoluteString];
    for (id delegate in delegateArray) {
        
        if(delegate != nil && [delegate respondsToSelector:@selector(imageDidDownloadFailed:)]) {
        
            [delegate imageDidDownloadFailed:imageURL];
        }
    }
    
    // Remove the key & value.
    [_delegateDict removeObjectForKey:imageURL.absoluteString];
}

@end
